//////////////////////////////////////////////////////////////////////////////
//
// File:  bot.h
// 
// Description: 
//   This file contains a bot class object that controls and utilizes all the
//   bot commands and text outputs.  It receives its data from bnet from
//   conGuy.  The interface to bnet is through the conGuy, and it does it's
//   receives/sends via conGuy's gimmeEvent() function, conGuy's sendQueue,
//   and conGuy's sendRequests.
//   
//
#ifndef BOT_H
#define BOT_H



// ChangeLog:
// 
// Version 1.00
//   Initial completion of the bot.  I think I did all the commands I wanted
//   to do.  We'll see as I go.
// Version 1.01
//   Made it so the !allseen outputs 10 users in the first send, not 9.
//   (i % 11), where i starts as 1;  Search for i % 11.
// Version 1.02
//   !ver does the same thing as !version, and 'pee pee' changed to 'peepee'
//   for !love command.  Added !whoami.
// Version 1.03
//   Fixed some poll problems so it doesn't just die if there's an weird error.
// Version 1.04
//   Made all SID_PING returns to be required to sleep as well.  Added
//   more *debug output with timestamps for the SID_PINGs.
// Version 1.05
//   Hopefully fixed the issues with kicking and banning.  They were:
//     1.  Kicking and Banning admins don't work anymore.
//     2.  Banned users actually get their banned bit in database switched 
//           to true.
//     3.  Banned users joining the channel get rebanned (kicked).
//   For the exit command, a timestamp is logged in botlog.
//   Created connect and disconnect commands for specified gateways.
//   Enhanced the reconnect command to be able to specify gateways.
// Version 1.06
//   Apparently, the connect command didn't really work right.  I fixed
//   the precedural part of the whole conGuy - up and conGuy -down thing
//   (I think?).  I also have it so it purges the sendQueue and the 
//   sendRequests (hopefully) correctly.
// Version 1.07
//   Made it so ops can't promote another user to ops as well.
// Version 1.08
//   Fixed the revents == 0x19 0x00, so that in a poll error, there is a switch
//   statement that can properly (with bitwise or: | ) take care of it.
//   (hopefully).
// Version 1.09
//   Increased time to the 'sleepRequiredTime()' function.  It was flooding
//   when someone sent a lot of botmails to a person.
// Version 1.10
//   Fixed the !mail command so that it will not let you mail to a non-existant
//   user (in our database).  Added !forcemail for that purpose.  Also made
//   commands case-insensitive.  Added !deloutmail command and the 
//   !outbox command.
// Version 1.11
//   Made the deloutmail and !outbox much more intuitive to use.
// Version 1.12
//   My promote command was kinda screwy.  Hopefully fixed that.
// Version 1.13
//   8/9/2004:
//     I think I have found the problem to why the program sometimes crashes
//     after a few days worth of running.  It will sometimes recieve a
//     SID_CHATEVENT, and then when we do an extract on it, the text field
//     comes out all bad.  Dunno how, but anyways, there are a lot of 0xFF's 
//     in it, which is obviously the UTF-8.  And since most of my stuff is
//     for just the ascii part of it, the 0xFF REALLY should be just 
//     characters that won't display right.  I'm not sure what I should do
//     at this point, but for now I will just ignore all characters that are
//     out of the ascii range.  Hopefully this won't break anything.  If it
//     does... I know where to look.   *_*.  Modifying:  conGuy/buff.cc,
//     function bool buff::extract(char *stuff).
// Version 1.14
//   8/14/2004
//     To fix the SID_NULL thing of when it should be sent, but I'm not
//     sending it, I'm going to just send a arbitrary msg to the channel.
//     A simple fix, yes, and we'll see how it turns out.  This mod was in
//     the gimmeEvent() function in conGuy/conGuy.cc.
//     I also commented out some of the debug output to the *debug file stream.
// Version 1.15
//   2/26/2005
//     Updated the bot to hold the new Starcraft Brood War v 1.12 login values.
//     Also, added support to include the bot.cfg option of no log files.
// Version 1.16
//   3/26/2005
//     Added a !dice function to roll a n-sided dice.  Took out the rock 
//     paper scissors one.  Also, I upped some sleep times for when 
//     the bot is reconnecting.
// Version 1.17
//   4/11/2005
//     The CheckRevision hashing is now correct.  Also, exeVer is now
//     correct for 1.12.  It changed on us somehow.
// Version 1.18
//   6/30/2005
//     Support for version 1.13.
//
// Features to add for newer versions:
//   See the 'TODO' file.


#define VERSION 1.18


#include<string>
#include<sqlite.h>
using namespace std;
#include "../conGuy/types.h"
#include "../conGuy/conGuy.h"
#include "../event/event.h"




// This class is used as a helper class to help parse and find and sort 
// botmails queued that we are looking for.  In particular, it is currently
// used in bool bot::cmd_outbox().  There may be other places. Search for'em~.
class botmail {
public:
  string userTo;
  string userFrom;
  string msg;
  time_t queueTime; 
};



// This class implements all the 'bot' functionality.  It organizes
// the team of 'conGuy's and micromanages their functionality and
// interfunctional requests.  The bot actually piggy-backs and runs
// off of one conGuy.  This is conGuy *bnet, which points to one of
// the gateway conGuys.
class bot {
 public:
  bot();
  ~bot();
  bool exec(bool &reExec);
 private:
  string unique_username;
  string curr_channel;
  event new_event; // This is a network/chat event that will be parsed.

  conGuy *bnet;    // bnet points to one of the following 4 conGuys
  conGuy *useast;
  conGuy *uswest;
  conGuy *europe;
  conGuy *asia;

  sqlite *db;  // Our database.
  ofstream botlog;  // Our bot log.

  bool reExecFlag;  // This is a flag that symbolizes if we the bot
		    // got a !reconnect cmd or a !exit cmd.  Mostly
		    // for giving info to int main().

  bool read_config();  // Read in the config file.

  bool spawn_threads_and_wait();  // spawns threads for chat event handlers.
  static void *chat_event_handler_callback(void *args);
  bool chat_event_handler(conGuy *myConGuy);
  
  // Configured options from config file.
  string database_file;
  string admin_accnt;
  string chatlog_file_base;

  // Most of these variables aren't used, but they are read in still.
  bool bot_chatlog;
  bool bot_cmds;
  bool bot_mail;
  bool bot_mailops;
  bool bot_mailall;
  bool bot_allseen;
  bool bot_seen;
  bool bot_banlist;
  bool bot_beep;
  bool bot_admin;
  bool bot_greet;
  bool bot_say;
  bool bot_say_exact;
  bool bot_smackdown;
  bool bot_mama_smackdown;
  bool bot_polls;    // polls and votes
  

  // Some functions...
  string get_timestamp();

  // Parsing for a bot comamnd.  In the form "!command-name-here ..."
  bool parse_for_commands(event e, conGuy* myConGuy);
  // Parse for a the status of a request to whisper another gateway.
  // It parses an event that could give us more insight on requests
  // that have been fulfilled.
  bool parse_for_request_status(event ev, conGuy* myConGuy);


  // Displays help and available commands.
  bool cmd_help(const event ev, conGuy *myConGuy, const string command, 
		const string arg1);
  // Random, heads or tails.
  bool cmd_cointoss(const event ev, conGuy *myConGuy);
  // Randomly roll a n-sided dice.
  bool cmd_dice(const event ev, conGuy *myConGuy, const string sides);
  // Returns the time.
  bool cmd_time(const event ev, conGuy *myConGuy);
  // Whispers the specified person.
  bool cmd_whisper(const event ev, conGuy *myConGuy, const string command, 
		   const string arg1, const string after_arg1);
  // Whereis request accross all gateways.
  bool cmd_whereis(const event ev, conGuy *myConGuy, 
		   const string command, const string arg1);
  // Display GiTMbot version.
  bool cmd_version(const event ev, conGuy *myConGuy);
  // Tell the bot to say something.  (prepended by the user who requested).
  bool cmd_say(const event ev, conGuy *myConGuy, const string msg);
  // Tell the bot to say something exactly.  (admin-only command).
  bool cmd_sayexact(const event ev, conGuy *myConGuy, const string msg);
  // Botmail a person.
  bool cmd_mail(const event ev, conGuy *myConGuy, const string mailTo, 
		const string msg);
  // Botmail a person non-existant in our database..
  bool cmd_forcemail(const event ev, conGuy *myConGuy, const string mailTo, 
		     const string msg);
  // Mail all operators.
  bool cmd_mailops(const event ev, conGuy *myConGuy, const string msg);
  // Check the last 'number' of people seen in the channel.
  bool cmd_allseen(const event ev, conGuy *myConGuy, const int number);
  bool cmd_allseen(const event ev, conGuy *myConGuy);

  // Check the inbox or outbox.
  bool cmd_inbox(const event ev, conGuy *myConGuy);
  bool cmd_outbox(const event ev, conGuy *myConGuy, string userTo);

  // This is a helper function to cmd_outbox.
  bool returnResultsToCmdOutbox(conGuy *myConGuy, string userFrom, 
				list<botmail> matchingMails);
  // Delete outgoing botmail.
  bool cmd_deloutmail(const event ev, conGuy *myConGuy, 
		      list<string> botmailIDs);
  // Displays the users that are banned.
  bool cmd_banned(const event ev, conGuy *myConGuy);
  // Displays the users that are operators.
  bool cmd_operators(const event ev, conGuy *myConGuy);
  // Displays the users that are adiministrators.
  bool cmd_administrators(const event ev, conGuy *myConGuy);
  // Displays the rank of the user specified. 
  bool cmd_whois(const event ev, conGuy *myConGuy, const string name);
  // Promote a user 1 rank level.
  bool cmd_promote(const event ev, conGuy *myConGuy, const string name);
  // Promote a user to the highest rank, admin.
  bool cmd_promotetoadmin(const event ev, conGuy *myConGuy, const string name);
  // Demote a user 1 rank level.
  bool cmd_demote(const event ev, conGuy *myConGuy, const string name);
  // Tells when the last time a user was seen.
  bool cmd_seen(const event ev, conGuy *myConGuy, const string name);
  // Gives a user some love. ;)
  bool cmd_love(const event ev, conGuy *myConGuy, const string name);
  // Gives a user a smackdown. ;)
  bool cmd_smackdown(const event ev, conGuy *myConGuy, const string name);
  // Bans a user and optionally provides a messages to them for why.
  bool cmd_ban(const event ev, conGuy *myConGuy, const string name,
	       const string message);
  // Unbans a user.
  bool cmd_unban(const event ev, conGuy *myConGuy, const string name);
  // Kicks a user and optionally provides a messages to them for why.
  bool cmd_kick(const event ev, conGuy *myConGuy, const string name, 
		const string message);
  // Display bot uptime.
  bool cmd_uptime(const event ev, conGuy *myConGuy);
  // These 3 functions are specific to the gateway specified or to the
  // whole bot program as a whole if no gateway is specified.
  bool cmd_connect(const event ev, conGuy *myConGuy, const string gateway);
  bool cmd_reconnect(const event ev, conGuy *myConGuy, const string gateway);
  bool cmd_disconnect(const event ev, conGuy *myConGuy, const string gateway);
  // Exit the bot. 
  bool cmd_exit(const event ev, conGuy *myConGuy);

  

  // SQL intensive commands.  Pretty much self explainitory.
  bool open_sql_db();
  bool update_user(string username);
  bool has_mail(string username);
  bool user_exists(string username);
  bool create_new_user(string username, bool havemail);
  bool create_new_user(string username, bool havemail, time_t seentime);
  bool queue_mail(string userfrom, string userto, string message);
  bool mail_ops(string userfrom, string message);
  bool check_mail(string userto, string &userfrom, time_t &queueTime, 
		  string &msg);
  bool remove_mail(string userfrom, string userto, time_t queueTime);
  bool remove_mail(string userfrom, time_t queueTime);
  bool allseen(list<string> &allseenList, int number);
  bool banned(list<string> &bannedList);
  bool operators(list<string> &operatorsList);
  bool administrators(list<string> &administratorsList);

  bool userIsBanned(string username);
  bool userIsGuest(string username);
  bool userIsRegular(string username);
  bool userIsOperator(string username);
  bool userIsAdministrator(string username);

  bool promoteUserToAdmin(string username);
  bool promoteUser(string username);
  bool demoteUser(string username);
  bool banUser(string username);
  bool unBanUser(string username);
  time_t seenUser(string username);


};




// This is a struct that is passed to the threads when they are spawned
// as callback parameters.  It gives the thread some info about itself and
// the particular bot or conGuy it should be taking care of.
struct bot_and_conGuy_t {
  bot *aBot;
  conGuy *aConGuy;
};



// Event ID's

#define EID_SHOWUSER			0x01  
#define EID_JOIN			0x02  
#define EID_LEAVE			0x03
#define EID_WHISPER			0x04  
#define EID_TALK			0x05  
#define EID_BROADCAST			0x06  
#define EID_CHANNEL			0x07  
#define EID_USERFLAGS			0x09  
#define EID_WHISPERSENT			0x0A  
#define EID_CHANNELFULL			0x0D  
#define EID_CHANNELDOESNOTEXIST		0x0E  
#define EID_CHANNELRESTRICTED		0x0F  
#define EID_INFO			0x12
#define EID_ERROR			0x13
#define EID_EMOTE			0x17  



// Channel flags.

#define CHANNEL_PUBLIC			0x01  
#define CHANNEL_MODERATED		0x02  
#define CHANNEL_RESTRICTED		0x04  
#define CHANNEL_SILENT			0x08  
#define CHANNEL_SYSTEM			0x10  
#define CHANNEL_PRODUCTSPECIFIC		0x20 
#define CHANNEL_GLOBAL			0x1000  



// User flags.

#define USER_BLIZZREP			0x01  
#define USER_CHANNELOP			0x02  
#define USER_SPEAKER			0x04  
#define USER_ADMIN			0x08  
#define USER_NOUDP			0x10  
#define USER_SQUELCHED			0x20  
#define USER_GUEST			0x40  
#define USER_BEEPENABLED		0x100  
#define USER_PGLPLAYER			0x200  
#define USER_PGLOFFICIAL		0x400  
#define USER_KBKPLAYER			0x800  
#define USER_KBKOFFICIAL		0x1000  
#define USER_JAILED			0x100000  
#define USER_GFPLAYER			0x200000  





// Event ID's.

#define EID_SHOWUSER			0x01  
#define EID_JOIN			0x02  
#define EID_LEAVE			0x03  
#define EID_WHISPER			0x04  
#define EID_TALK			0x05  
#define EID_BROADCAST			0x06  
#define EID_CHANNEL			0x07  
#define EID_USERFLAGS			0x09  
#define EID_WHISPERSENT			0x0A  
#define EID_CHANNELFULL			0x0D  
#define EID_CHANNELDOESNOTEXIST		0x0E  
#define EID_CHANNELRESTRICTED		0x0F  
#define EID_INFO			0x12  
#define EID_ERROR			0x13  
#define EID_EMOTE			0x17  


#endif


//////////////////////////////////////////////////////////////////////////////
// End of file
//////////////////////////////////////////////////////////////////////////////
